#include "gui/VisualComponents/VisualComponentSegment.h"
#include "gui/VisualComponents/VisualComponentVia.h"
#include "gui/VisualComponents/ArrowLine.h"
#include "gui/VisualComponents/ArrowOpen.h"
#include "gui/VisualComponents/ArrowSolid.h"
#include "gui/VisualComponents/ArrowDiamond.h"

VisualComponentSegment::VisualComponentSegment(Point* start, Point* end, bool isVertical, ArrowHead::ArrowStyle style){
	m_isVertical = isVertical;
	m_lastSegment = false;
	m_startPoint = start;
	m_endPoint = end;
	m_arrowHead = NULL;
	m_arrow_style = style;
	m_orientation = NONE;
	updateArrowStyle();
}

VisualComponentSegment::~VisualComponentSegment() {
	delete m_arrowHead;
}

InfluenceArea VisualComponentSegment::getInfluenceArea() {
	int halfwidth = round(ANCHO_DE_LINEA / 2);
	if (isVertical())
		return InfluenceArea(InfluenceRectangle( m_startPoint->getX() - halfwidth , m_startPoint->getY(), m_endPoint->getX() + halfwidth, m_endPoint->getY()));
	else
		return InfluenceArea(InfluenceRectangle( m_startPoint->getX(), m_startPoint->getY() + halfwidth, m_endPoint->getX(), m_endPoint->getY() - halfwidth));
}

bool VisualComponentSegment::isVertical(){
	return m_isVertical;
}

void VisualComponentSegment::on_expose(Cairo::RefPtr<Cairo::Context> ptrContext) {
	draw(ptrContext);
}

void VisualComponentSegment::on_move(int mouseX, int mouseY) {

}

void VisualComponentSegment::draw(Cairo::RefPtr<Cairo::Context> ptrContext) {
//	std::cout << "start: (" << m_startPoint->getX() << ", " << m_startPoint->getY() << ")  " << "end  : (" <<   m_endPoint->getX() << ", " <<   m_endPoint->getY() << ")" << std::endl;

	ptrContext->save();
	if (m_selected)
		ptrContext->set_source_rgb(0, 1, 0);
	else
		ptrContext->set_source_rgb(0, 0, 0);
	ptrContext->set_line_width(ANCHO_DE_LINEA);
	if (m_arrow_style == ArrowHead::ARROW_OPEN) {
		double DASH_STYLE_LENGHT = 7.0;
		std::valarray< double > dashes(2);
		dashes[0] = dashes[1] = DASH_STYLE_LENGHT;
		ptrContext->set_dash (dashes, 0.0);
		ptrContext->move_to(m_startPoint->getX(), m_startPoint->getY());
		ptrContext->line_to(m_endPoint->getX(), m_endPoint->getY());
		ptrContext->stroke();
	}else{
		ptrContext->move_to(m_startPoint->getX(), m_startPoint->getY());
		ptrContext->line_to(m_endPoint->getX(), m_endPoint->getY());
		ptrContext->stroke();
	}
	ptrContext->restore();
	ptrContext->save();
	if (m_arrowHead != NULL && m_lastSegment){
		if (m_orientation == NORTH)
			m_arrowHead->draw(ptrContext, m_endPoint->getX(),
					m_startPoint->getY(), m_endPoint->getX(),
					m_endPoint->getY() + 15);
		else if (m_orientation == SOUTH)
			m_arrowHead->draw(ptrContext, m_endPoint->getX(),
					m_startPoint->getY(), m_endPoint->getX(),
					m_endPoint->getY() - 15);
		else
			m_arrowHead->draw(ptrContext, m_startPoint->getX(),
					m_startPoint->getY(), m_endPoint->getX(),
					m_endPoint->getY());
	}
	ptrContext->restore();
}

int VisualComponentSegment::getX() const{
	return m_startPoint->getX();
}

void VisualComponentSegment::setX(int x){
	std::cout << "VisualComponentSegment::setX" << std::endl;
}

int VisualComponentSegment::getY() const{
	return m_startPoint->getY();
}

void VisualComponentSegment::setY(int y){
	std::cout << "VisualComponentSegment::setX" << std::endl;
}

int VisualComponentSegment::getLength() {
	return isVertical() ? abs(m_endPoint->getY() - m_startPoint->getY()) :  abs(m_endPoint->getX() - m_startPoint->getX());
}

bool VisualComponentSegment::isMobile() {
	return m_startPoint->isMobile() && m_endPoint->isMobile();
}

void VisualComponentSegment::setAsLastSegment(){
	m_lastSegment = true;
}

void VisualComponentSegment::setNotAsLastSegment(){
	m_lastSegment = false;
}

void VisualComponentSegment::setOrientation(enum Orientation o){
	m_orientation = o;
}

void VisualComponentSegment::updateArrowStyle()
{
	if (m_arrow_style == ArrowHead::ARROW_OPEN) {
		m_arrowHead = new ArrowOpen();
	} else if (m_arrow_style == ArrowHead::ARROW_SOLID) {
		m_arrowHead = new ArrowSolid();
	} else if (m_arrow_style == ArrowHead::ARROW_DIAMOND_FILLED) {
		m_arrowHead = new ArrowDiamond(true);
	} else if (m_arrow_style == ArrowHead::ARROW_DIAMOND) {
		m_arrowHead = new ArrowDiamond(false);
	} else if (m_arrow_style == ArrowHead::ARROW_LINE) {
		m_arrowHead = new ArrowLine();
	}
}

Point *VisualComponentSegment::getStartPoint() const
{
    return m_startPoint;
}

void VisualComponentSegment::setStartPoint(Point *startPoint)
{
    m_startPoint = startPoint;
}

Point *VisualComponentSegment::getEndPoint() const
{
    return m_endPoint;
}

void VisualComponentSegment::setEndPoint(Point *endPoint)
{
     m_endPoint = endPoint;
}
